/**
 * @File name: script/config/conf.c
 * @Synopsis:
 * @Author: xing.dai@aliyun.com
 * @Version: 0.0.1
 * @Date: 2018-08-09 17:13
 */

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

#define LINE_LEN					256
#define READ_BUF_LINE_LEN			256
#define WRITE_BUF_LINE_LEN			256

#if 1
#define DEFCONFIG_DEBUG_INFO	1
#define conf_dbg(x_format, ...)	printf(x_format, ##__VA_ARGS__)
#else
#define DEFCONFIG_DEBUG_INFO	0
#define conf_dbg(x_format, ...)
#endif

static char *trim(char *str)
{
    int i = 0;
    int j = strlen(str) - 1;
    int len = 0;

    while (str[i] == ' ' || str[i] == '\0')
        i++;
    while (str[j] == ' ' || str[j] == '\0' || str[j] == '\r' || str[j] == '\n')
        j--;

    len = j - i + 1;
    if (len < strlen(str)) {
        for (j = 0; j < len; j++)
            str[j] = str[j + i];
        str[len] = '\0';
    }

    return str;
}

static int analysis_defconfig_file(char *read_line, char *wr_conf_line, char *wr_h_line)
{
    int i = 0;
    const char *prefix = "#define ";
    char *rd_buf = read_line;
    char name[LINE_LEN];
    char value[LINE_LEN];
    char wr_h_buf[LINE_LEN];
    char wr_conf_buf[LINE_LEN];

    memset(name, 0x00, LINE_LEN);
    memset(value, 0x00, LINE_LEN);
    memset(wr_h_buf, 0x00, LINE_LEN);
    memset(wr_conf_buf, 0x00, LINE_LEN);

    while (*rd_buf != '=') {
        name[i] = *rd_buf;
        i++;
        rd_buf++;
    }

    trim(name);

    if (*rd_buf == '=') {
        rd_buf++;
    }

    strcpy(value, rd_buf);
    trim(value);

    /* .config */
    strcat(wr_conf_buf, name);
    strcat(wr_conf_buf, " := ");
    strcat(wr_conf_buf, value);
    strcat(wr_conf_buf, "\n");

    /* includes/auto_conf.h */
    strcat(wr_h_buf, prefix);
    strcat(wr_h_buf, name);

    if (*value == 'y' && strlen(value) == 1) {
        /* Only define.*/
    } else {
        strcat(wr_h_buf, "\t\t");
        if (*value == '"') {
            strcat(wr_h_buf, value);
        } else {
            strcat(wr_h_buf, "\"");
            strcat(wr_h_buf, value);
            strcat(wr_h_buf, "\"");
        }
    }
    strcat(wr_h_buf, "\n");

    strcpy(wr_conf_line, wr_conf_buf);
    strcpy(wr_h_line, wr_h_buf);
    return 0;
}

/**
 * @Synopsis  make xxx_defconfig
 *
 * @Param argc 2.
 * @Param argv [0] = conf    [1] = ./configs/xxx_defconfig
 *
 * @Returns
 */
int main(int argc, char **argv)
{
    int i;
    FILE *def_fd;		/* xxx_defconfig */
    FILE *auto_conf_fd;	/* .config in topdir. */
    FILE *auto_h_fd;	/* auto_config.h */
    char *defconfig_filename;
    char **input_argv = argv;
    char read_buf[READ_BUF_LINE_LEN];
    char write_conf_buf[WRITE_BUF_LINE_LEN];
    char write_h_buf[WRITE_BUF_LINE_LEN];
    const char *auto_h_filename = "./include/auto_config.h";
    const char *auto_conf_filename = "./.config";

    if (argc < 2) {
        printf("Usage: make xxx_defconfig.\n");
        return 0;
    }
#if 0
    for (i = 0; i < argc; i++) {
        printf("argv[%d]: %s\n", i, *input_argv);
        input_argv++;
    }
#endif

    defconfig_filename = *(argv + 1);
    if ((def_fd = fopen(defconfig_filename, "r")) == NULL) {
        printf("Read defconfig files: %s Error! Check file exist?\n", defconfig_filename);
        return 0;
    }

    if ((auto_conf_fd = fopen(auto_conf_filename, "w")) == NULL) {
        printf("Can not create: %s\n", auto_conf_filename);
        return 0;
    }

    if ((auto_h_fd = fopen(auto_h_filename, "w")) == NULL) {
        printf("Can not create: %s\n", auto_h_filename);
        return 0;
    }

    fprintf(auto_h_fd, "#ifndef __AUTO_CONFIG_H__\n");
    fprintf(auto_h_fd, "#define __AUTO_CONFIG_H__\n\n");

    while (!feof(def_fd)) {
        while (fgets(read_buf, READ_BUF_LINE_LEN, def_fd) != NULL && read_buf[0] != '\n') {
            analysis_defconfig_file(read_buf, write_conf_buf, write_h_buf);
            fprintf(auto_conf_fd, "%s", write_conf_buf);
            fprintf(auto_h_fd, "%s", write_h_buf);
        }
    }
    fprintf(auto_h_fd, "\n#endif\n");

    fclose(def_fd);
    fclose(auto_conf_fd);
    fclose(auto_h_fd);
    return 0;
}

